home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Magazin: Amiga-CD 1997 July & August
/
Amiga-CD 1997 #7-8.iso
/
pd-disketten
/
dms-gepackt
/
4_96
/
apd-4-96-2.dms
/
apd-4-96-2.adf
/
Gut gekurvt
/
PsZeichnen.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-13
|
8KB
|
186 lines
// Bézier-Kurven; (C) C. Marschner, 1996
// PsZeichnen:
// Zeichnet nach den Informatinen im Array (s.u.) den Buchstaben "P"
// in verschiedenen Größen
#include <intuition/intuition.h>
#include <graphics/rastport.h>
#include <graphics/gfxmacros.h>
#include <pragma/intuition_lib.h>
#include <pragma/exec_lib.h>
#include <pragma/graphics_lib.h>
#include <pragma/dos_lib.h>
#include <math.h>
#include <stream.h>
double Bezier(struct RastPort *, double,double,double,double,
double,double,double,double,double,int);
// Die Daten, um leichter skaliert werden zu können, etwa zwischen 0 u. 1
static double p[][4][2] = { // "P"
{{ 0.000,0.000},{0.150,0.050}, {0.200,0.050}, {0.250,0.030}},
{{ 0.250,0.030},{0.300,0.010}, {0.350,0.000}, {0.400,0.000}},
{{ 0.400,0.000},{0.700,0.000}, {0.775,0.250}, {0.775,0.400}},
{{ 0.775,0.400},{0.775,0.650}, {0.700,0.700}, {0.450,0.700}},
{{ 0.450,0.700},{0.350,0.700}, {0.330,0.660}, {0.270,0.660}},
{{ 0.270,0.660},{0.230,0.660}, {0.200,0.660}, {0.200,0.700}},
{{ 0.200,0.700},{0.200,0.700}, {0.200,0.950}, {0.200,0.950}},
{{ 0.200,0.950},{0.180,1.000}, {0.160,1.000}, {0.250,1.030}},
{{ 0.250,1.030},{0.320,1.045}, {0.340,1.040}, {0.360,1.075}},
{{ 0.360,1.075},{0.170,1.040}, {0.100,1.030}, {-0.08,1.100}},
{{ -0.08,1.100},{-0.10,1.050}, {-0.06,1.025}, {0.030,1.025}},
{{ 0.030,1.025},{0.100,1.010}, {0.100,1.010}, {0.100,0.950}},
{{ 0.100,0.950},{0.100,0.950}, {0.100,0.200}, {0.100,0.200}},
{{ 0.100,0.200},{0.100,0.110}, {0.090,0.100}, {0.000,0.100}},
{{ 0.000,0.100},{0.000,0.010}, {0.000,0.000}, {0.000,0.000}},
{{ 0.200,0.150},{0.210,0.080}, {0.300,0.050}, {0.450,0.050}},
{{ 0.450,0.050},{0.590,0.050}, {0.650,0.150}, {0.650,0.400}},
{{ 0.650,0.400},{0.650,0.600}, {0.630,0.650}, {0.450,0.650}},
{{ 0.450,0.650},{0.400,0.650}, {0.400,0.650}, {0.350,0.630}},
{{ 0.350,0.630},{0.260,0.605}, {0.300,0.610}, {0.200,0.610}},
{{ 0.200,0.610},{0.200,0.610}, {0.200,0.150}, {0.200,0.150}},
};
/*
struct Screen *scn = OpenScreenTags
(NULL,
SA_Depth, 2, SA_Width, 640,
SA_Height, 523, SA_Quiet, TRUE,
SA_Type, CUSTOMSCREEN|AUTOSCROLL, SA_DisplayID, PAL_MONITOR_ID|HIRESLACE_KEY,
SA_Pens, pens,
TAG_END
);
*/
struct Window *win = OpenWindowTags
(NULL,
WA_Flags, WFLG_ACTIVATE|WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_DRAGBAR|
WFLG_NOCAREREFRESH|WFLG_SIMPLE_REFRESH|
WFLG_DEPTHGADGET|WFLG_REPORTMOUSE,
WA_Top, 11, WA_Width, 640,
WA_Height, 512, WA_Left, 0,
WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE,
/* WA_CustomScreen, scn, */
WA_BlockPen, 4, WA_DetailPen, 3,
WA_Title, (char*)"Bézier-Kurven...",
TAG_END
);
struct RastPort *rp = win->RPort;
int status = 0;
void main() {
double k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y;
int zaehler = 0;
TmpRas tmpr;
AreaInfo ai;
if(!win) { CloseWindow(win); return };
try {
SetAPen(rp,1);
// Das Programm benutzt AreaMove/AreaDraw, um den Buchstaben zu füllen.
// Dazu muß erstmal ein TmpRas besorgt, eine AreaInfo fertiggemacht und
// das ganze in den RastPort eingetragen werden
// 1. Raster für AreaDraw fertigmachen:
PLANEPTR tr = AllocRaster(640,512); // anfordern
if(!tr) // -> Fehler Nummer drei auswerfen
throw(3);
InitTmpRas(&tmpr, tr, RASSIZE(640,512)); // initialisieren
rp->TmpRas = &tmpr; // und eintragen
char *buffer = (char*)new WORD[25*5*21+50]; // Puffer für Koordinaten
InitArea(&ai, buffer, 50*21); // AreaInfo-Liste
AreaInfo *old = rp->AreaInfo; // und austauschen
rp->AreaInfo = &ai;
BNDRYOFF(rp); // Ausschalten des Rahmen-Pens
// 2. Jetzt kann AreaMove/Draw benutzt werden.
// 6 mal zeichnen
for(int j = 0; j < 6; j++) {
double range = 0;
SetAPen(rp,1);
// Das äußere vom "P": zwei Reihen a 3 Buchstaben; 6 Größen
for(int i=0; i<15; i++)
{
// Die Transformation ist weniger kompliziert, als sie aussieht
// Die Figur wird auf 150 Punkt gestreckt, wobei bei jedem weiteren
// "P" die Figur um 15 Pkt. größer wird. Schließlich wird noch der
// Nullpunkt verschoben, wobei ab j=3 eine zweite Zeile aufgemacht wird
k1x = p[i][0][0] * (120.0+ 20*j) + 50.0 + 160.0 * (j<3?j:j-3);
k1y = p[i][0][1] * (120.0+ 20*j) + 50.0 + 190.0 * (j>2);
k2x = p[i][1][0] * (120.0+ 20*j) + 50.0 + 160.0 * (j<3?j:j-3);
k2y = p[i][1][1] * (120.0+ 20*j) + 50.0 + 190.0 * (j>2);
k3x = p[i][2][0] * (120.0+ 20*j) + 50.0 + 160.0 * (j<3?j:j-3);
k3y = p[i][2][1] * (120.0+ 20*j) + 50.0 + 190.0 * (j>2);
k4x = p[i][3][0] * (120.0+ 20*j) + 50.0 + 160.0 * (j<3?j:j-3);
k4y = p[i][3][1] * (120.0+ 20*j) + 50.0 + 190.0 * (j>2);
if(!i) AreaMove(rp,(long)k1x,(long)k1y);
Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,0,0);
}
AreaEnd(rp);
SetAPen(rp,0);
for(i=15; i<21; i++) {
k1x = p[i][0][0] * (120.0+20*j) + 50.0 + 160.0 * (j<3?j:j-3);
k1y = p[i][0][1] * (120.0+20*j) + 50.0 + 190.0 * (j>2);
k2x = p[i][1][0] * (120.0+20*j) + 50.0 + 160.0 * (j<3?j:j-3);
k2y = p[i][1][1] * (120.0+20*j) + 50.0 + 190.0 * (j>2);
k3x = p[i][2][0] * (120.0+20*j) + 50.0 + 160.0 * (j<3?j:j-3);
k3y = p[i][2][1] * (120.0+20*j) + 50.0 + 190.0 * (j>2);
k4x = p[i][3][0] * (120.0+20*j) + 50.0 + 160.0 * (j<3?j:j-3);
k4y = p[i][3][1] * (120.0+20*j) + 50.0 + 190.0 * (j>2);
if(i==15) AreaMove(rp,(long)k1x,(long)k1y);
Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,0,0);
}
AreaEnd(rp);
}
Delay(250); // 5 Sekunden warten
// 3. alte Werte wieder zurückschreiben:
delete buffer;
rp->AreaInfo = old;
rp->TmpRas = 0;
FreeRaster(tr,640,512);
} catch(int n) {
if(n>1) cout << "Fehler "<< n << "\n";
}
CloseWindow(win);
}
double Bezier(struct RastPort *rp,
double k0x,double k0y,double k1x,double k1y,
double k2x,double k2y,double k3x,double k3y, double nr,int flag)
{
double bx, by, emt, emt2, t2, tm3, emtm3;
// improvisierte Abschätzung der Schrittweite:
const double range =
floor(10+(fabs(k0y-k1y)+fabs(k0x-k1x)+fabs(k1x-k2x)+
fabs(k1y-k2y)+fabs(k2x-k3x)+fabs(k2y-k3y))/30.0);
const double step = 1.0/range;
const double rst = range*step; // Konstante z. schnelleren Bearbeiten
AreaDraw(rp,(long)k0x,(long)k0y);
for(double t = step; t <= rst; t+= step)
{
emt = 1-t; emt2=emt*emt; t2=t*t; tm3=3*t; emtm3 = 3*emt;
bx = emt2*(emt*k0x + tm3*k1x) + t2*(emtm3*k2x + t*k3x);
by = emt2*(emt*k0y + tm3*k1y) + t2*(emtm3*k2y + t*k3y);
AreaDraw(rp,(long)bx,(long)by);
}
return range;
}